package goqueryimporttype siblingType int// Sibling type, used internally when iterating over children at the same// level (siblings) to specify which nodes are requested.const ( siblingPrevUntil siblingType = iota - 3 siblingPrevAll siblingPrev siblingAll siblingNext siblingNextAll siblingNextUntil siblingAllIncludingNonElements)// Find gets the descendants of each element in the current set of matched// elements, filtered by a selector. It returns a new Selection object// containing these matched elements.//// Note that as for all methods accepting a selector string, the selector is// compiled and applied by the cascadia package and inherits its behavior and// constraints regarding supported selectors. See the note on cascadia in// the goquery documentation here:// https://github.com/PuerkitoBio/goquery?tab=readme-ov-file#apifunc ( *Selection) ( string) *Selection {returnpushStack(, findWithMatcher(.Nodes, compileMatcher()))}// FindMatcher gets the descendants of each element in the current set of matched// elements, filtered by the matcher. It returns a new Selection object// containing these matched elements.func ( *Selection) ( Matcher) *Selection {returnpushStack(, findWithMatcher(.Nodes, ))}// FindSelection gets the descendants of each element in the current// Selection, filtered by a Selection. It returns a new Selection object// containing these matched elements.func ( *Selection) ( *Selection) *Selection {if == nil {returnpushStack(, nil) }return .FindNodes(.Nodes...)}// FindNodes gets the descendants of each element in the current// Selection, filtered by some nodes. It returns a new Selection object// containing these matched elements.func ( *Selection) ( ...*html.Node) *Selection {returnpushStack(, mapNodes(, func( int, *html.Node) []*html.Node {ifsliceContains(.Nodes, ) {return []*html.Node{} }returnnil }))}// Contents gets the children of each element in the Selection,// including text and comment nodes. It returns a new Selection object// containing these elements.func ( *Selection) () *Selection {returnpushStack(, getChildrenNodes(.Nodes, siblingAllIncludingNonElements))}// ContentsFiltered gets the children of each element in the Selection,// filtered by the specified selector. It returns a new Selection// object containing these elements. Since selectors only act on Element nodes,// this function is an alias to ChildrenFiltered unless the selector is empty,// in which case it is an alias to Contents.func ( *Selection) ( string) *Selection {if != "" {return .ChildrenFiltered() }return .Contents()}// ContentsMatcher gets the children of each element in the Selection,// filtered by the specified matcher. It returns a new Selection// object containing these elements. Since matchers only act on Element nodes,// this function is an alias to ChildrenMatcher.func ( *Selection) ( Matcher) *Selection {return .ChildrenMatcher()}// Children gets the child elements of each element in the Selection.// It returns a new Selection object containing these elements.func ( *Selection) () *Selection {returnpushStack(, getChildrenNodes(.Nodes, siblingAll))}// ChildrenFiltered gets the child elements of each element in the Selection,// filtered by the specified selector. It returns a new// Selection object containing these elements.func ( *Selection) ( string) *Selection {returnfilterAndPush(, getChildrenNodes(.Nodes, siblingAll), compileMatcher())}// ChildrenMatcher gets the child elements of each element in the Selection,// filtered by the specified matcher. It returns a new// Selection object containing these elements.func ( *Selection) ( Matcher) *Selection {returnfilterAndPush(, getChildrenNodes(.Nodes, siblingAll), )}// Parent gets the parent of each element in the Selection. It returns a// new Selection object containing the matched elements.func ( *Selection) () *Selection {returnpushStack(, getParentNodes(.Nodes))}// ParentFiltered gets the parent of each element in the Selection filtered by a// selector. It returns a new Selection object containing the matched elements.func ( *Selection) ( string) *Selection {returnfilterAndPush(, getParentNodes(.Nodes), compileMatcher())}// ParentMatcher gets the parent of each element in the Selection filtered by a// matcher. It returns a new Selection object containing the matched elements.func ( *Selection) ( Matcher) *Selection {returnfilterAndPush(, getParentNodes(.Nodes), )}// Closest gets the first element that matches the selector by testing the// element itself and traversing up through its ancestors in the DOM tree.func ( *Selection) ( string) *Selection { := compileMatcher()return .ClosestMatcher()}// ClosestMatcher gets the first element that matches the matcher by testing the// element itself and traversing up through its ancestors in the DOM tree.func ( *Selection) ( Matcher) *Selection {returnpushStack(, mapNodes(.Nodes, func( int, *html.Node) []*html.Node {// For each node in the selection, test the node itself, then each parent // until a match is found.for ; != nil; = .Parent {if .Match() {return []*html.Node{} } }returnnil }))}// ClosestNodes gets the first element that matches one of the nodes by testing the// element itself and traversing up through its ancestors in the DOM tree.func ( *Selection) ( ...*html.Node) *Selection { := make(map[*html.Node]bool)for , := range { [] = true }returnpushStack(, mapNodes(.Nodes, func( int, *html.Node) []*html.Node {// For each node in the selection, test the node itself, then each parent // until a match is found.for ; != nil; = .Parent {if [] {return []*html.Node{} } }returnnil }))}// ClosestSelection gets the first element that matches one of the nodes in the// Selection by testing the element itself and traversing up through its ancestors// in the DOM tree.func ( *Selection) ( *Selection) *Selection {if == nil {returnpushStack(, nil) }return .ClosestNodes(.Nodes...)}// Parents gets the ancestors of each element in the current Selection. It// returns a new Selection object with the matched elements.func ( *Selection) () *Selection {returnpushStack(, getParentsNodes(.Nodes, nil, nil))}// ParentsFiltered gets the ancestors of each element in the current// Selection. It returns a new Selection object with the matched elements.func ( *Selection) ( string) *Selection {returnfilterAndPush(, getParentsNodes(.Nodes, nil, nil), compileMatcher())}// ParentsMatcher gets the ancestors of each element in the current// Selection. It returns a new Selection object with the matched elements.func ( *Selection) ( Matcher) *Selection {returnfilterAndPush(, getParentsNodes(.Nodes, nil, nil), )}// ParentsUntil gets the ancestors of each element in the Selection, up to but// not including the element matched by the selector. It returns a new Selection// object containing the matched elements.func ( *Selection) ( string) *Selection {returnpushStack(, getParentsNodes(.Nodes, compileMatcher(), nil))}// ParentsUntilMatcher gets the ancestors of each element in the Selection, up to but// not including the element matched by the matcher. It returns a new Selection// object containing the matched elements.func ( *Selection) ( Matcher) *Selection {returnpushStack(, getParentsNodes(.Nodes, , nil))}// ParentsUntilSelection gets the ancestors of each element in the Selection,// up to but not including the elements in the specified Selection. It returns a// new Selection object containing the matched elements.func ( *Selection) ( *Selection) *Selection {if == nil {return .Parents() }return .ParentsUntilNodes(.Nodes...)}// ParentsUntilNodes gets the ancestors of each element in the Selection,// up to but not including the specified nodes. It returns a// new Selection object containing the matched elements.func ( *Selection) ( ...*html.Node) *Selection {returnpushStack(, getParentsNodes(.Nodes, nil, ))}// ParentsFilteredUntil is like ParentsUntil, with the option to filter the// results based on a selector string. It returns a new Selection// object containing the matched elements.func ( *Selection) (, string) *Selection {returnfilterAndPush(, getParentsNodes(.Nodes, compileMatcher(), nil), compileMatcher())}// ParentsFilteredUntilMatcher is like ParentsUntilMatcher, with the option to filter the// results based on a matcher. It returns a new Selection object containing the matched elements.func ( *Selection) (, Matcher) *Selection {returnfilterAndPush(, getParentsNodes(.Nodes, , nil), )}// ParentsFilteredUntilSelection is like ParentsUntilSelection, with the// option to filter the results based on a selector string. It returns a new// Selection object containing the matched elements.func ( *Selection) ( string, *Selection) *Selection {return .ParentsMatcherUntilSelection(compileMatcher(), )}// ParentsMatcherUntilSelection is like ParentsUntilSelection, with the// option to filter the results based on a matcher. It returns a new// Selection object containing the matched elements.func ( *Selection) ( Matcher, *Selection) *Selection {if == nil {return .ParentsMatcher() }return .ParentsMatcherUntilNodes(, .Nodes...)}// ParentsFilteredUntilNodes is like ParentsUntilNodes, with the// option to filter the results based on a selector string. It returns a new// Selection object containing the matched elements.func ( *Selection) ( string, ...*html.Node) *Selection {returnfilterAndPush(, getParentsNodes(.Nodes, nil, ), compileMatcher())}// ParentsMatcherUntilNodes is like ParentsUntilNodes, with the// option to filter the results based on a matcher. It returns a new// Selection object containing the matched elements.func ( *Selection) ( Matcher, ...*html.Node) *Selection {returnfilterAndPush(, getParentsNodes(.Nodes, nil, ), )}// Siblings gets the siblings of each element in the Selection. It returns// a new Selection object containing the matched elements.func ( *Selection) () *Selection {returnpushStack(, getSiblingNodes(.Nodes, siblingAll, nil, nil))}// SiblingsFiltered gets the siblings of each element in the Selection// filtered by a selector. It returns a new Selection object containing the// matched elements.func ( *Selection) ( string) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingAll, nil, nil), compileMatcher())}// SiblingsMatcher gets the siblings of each element in the Selection// filtered by a matcher. It returns a new Selection object containing the// matched elements.func ( *Selection) ( Matcher) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingAll, nil, nil), )}// Next gets the immediately following sibling of each element in the// Selection. It returns a new Selection object containing the matched elements.func ( *Selection) () *Selection {returnpushStack(, getSiblingNodes(.Nodes, siblingNext, nil, nil))}// NextFiltered gets the immediately following sibling of each element in the// Selection filtered by a selector. It returns a new Selection object// containing the matched elements.func ( *Selection) ( string) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingNext, nil, nil), compileMatcher())}// NextMatcher gets the immediately following sibling of each element in the// Selection filtered by a matcher. It returns a new Selection object// containing the matched elements.func ( *Selection) ( Matcher) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingNext, nil, nil), )}// NextAll gets all the following siblings of each element in the// Selection. It returns a new Selection object containing the matched elements.func ( *Selection) () *Selection {returnpushStack(, getSiblingNodes(.Nodes, siblingNextAll, nil, nil))}// NextAllFiltered gets all the following siblings of each element in the// Selection filtered by a selector. It returns a new Selection object// containing the matched elements.func ( *Selection) ( string) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingNextAll, nil, nil), compileMatcher())}// NextAllMatcher gets all the following siblings of each element in the// Selection filtered by a matcher. It returns a new Selection object// containing the matched elements.func ( *Selection) ( Matcher) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingNextAll, nil, nil), )}// Prev gets the immediately preceding sibling of each element in the// Selection. It returns a new Selection object containing the matched elements.func ( *Selection) () *Selection {returnpushStack(, getSiblingNodes(.Nodes, siblingPrev, nil, nil))}// PrevFiltered gets the immediately preceding sibling of each element in the// Selection filtered by a selector. It returns a new Selection object// containing the matched elements.func ( *Selection) ( string) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingPrev, nil, nil), compileMatcher())}// PrevMatcher gets the immediately preceding sibling of each element in the// Selection filtered by a matcher. It returns a new Selection object// containing the matched elements.func ( *Selection) ( Matcher) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingPrev, nil, nil), )}// PrevAll gets all the preceding siblings of each element in the// Selection. It returns a new Selection object containing the matched elements.func ( *Selection) () *Selection {returnpushStack(, getSiblingNodes(.Nodes, siblingPrevAll, nil, nil))}// PrevAllFiltered gets all the preceding siblings of each element in the// Selection filtered by a selector. It returns a new Selection object// containing the matched elements.func ( *Selection) ( string) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingPrevAll, nil, nil), compileMatcher())}// PrevAllMatcher gets all the preceding siblings of each element in the// Selection filtered by a matcher. It returns a new Selection object// containing the matched elements.func ( *Selection) ( Matcher) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingPrevAll, nil, nil), )}// NextUntil gets all following siblings of each element up to but not// including the element matched by the selector. It returns a new Selection// object containing the matched elements.func ( *Selection) ( string) *Selection {returnpushStack(, getSiblingNodes(.Nodes, siblingNextUntil,compileMatcher(), nil))}// NextUntilMatcher gets all following siblings of each element up to but not// including the element matched by the matcher. It returns a new Selection// object containing the matched elements.func ( *Selection) ( Matcher) *Selection {returnpushStack(, getSiblingNodes(.Nodes, siblingNextUntil, , nil))}// NextUntilSelection gets all following siblings of each element up to but not// including the element matched by the Selection. It returns a new Selection// object containing the matched elements.func ( *Selection) ( *Selection) *Selection {if == nil {return .NextAll() }return .NextUntilNodes(.Nodes...)}// NextUntilNodes gets all following siblings of each element up to but not// including the element matched by the nodes. It returns a new Selection// object containing the matched elements.func ( *Selection) ( ...*html.Node) *Selection {returnpushStack(, getSiblingNodes(.Nodes, siblingNextUntil,nil, ))}// PrevUntil gets all preceding siblings of each element up to but not// including the element matched by the selector. It returns a new Selection// object containing the matched elements.func ( *Selection) ( string) *Selection {returnpushStack(, getSiblingNodes(.Nodes, siblingPrevUntil,compileMatcher(), nil))}// PrevUntilMatcher gets all preceding siblings of each element up to but not// including the element matched by the matcher. It returns a new Selection// object containing the matched elements.func ( *Selection) ( Matcher) *Selection {returnpushStack(, getSiblingNodes(.Nodes, siblingPrevUntil, , nil))}// PrevUntilSelection gets all preceding siblings of each element up to but not// including the element matched by the Selection. It returns a new Selection// object containing the matched elements.func ( *Selection) ( *Selection) *Selection {if == nil {return .PrevAll() }return .PrevUntilNodes(.Nodes...)}// PrevUntilNodes gets all preceding siblings of each element up to but not// including the element matched by the nodes. It returns a new Selection// object containing the matched elements.func ( *Selection) ( ...*html.Node) *Selection {returnpushStack(, getSiblingNodes(.Nodes, siblingPrevUntil,nil, ))}// NextFilteredUntil is like NextUntil, with the option to filter// the results based on a selector string.// It returns a new Selection object containing the matched elements.func ( *Selection) (, string) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingNextUntil,compileMatcher(), nil), compileMatcher())}// NextFilteredUntilMatcher is like NextUntilMatcher, with the option to filter// the results based on a matcher.// It returns a new Selection object containing the matched elements.func ( *Selection) (, Matcher) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingNextUntil, , nil), )}// NextFilteredUntilSelection is like NextUntilSelection, with the// option to filter the results based on a selector string. It returns a new// Selection object containing the matched elements.func ( *Selection) ( string, *Selection) *Selection {return .NextMatcherUntilSelection(compileMatcher(), )}// NextMatcherUntilSelection is like NextUntilSelection, with the// option to filter the results based on a matcher. It returns a new// Selection object containing the matched elements.func ( *Selection) ( Matcher, *Selection) *Selection {if == nil {return .NextMatcher() }return .NextMatcherUntilNodes(, .Nodes...)}// NextFilteredUntilNodes is like NextUntilNodes, with the// option to filter the results based on a selector string. It returns a new// Selection object containing the matched elements.func ( *Selection) ( string, ...*html.Node) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingNextUntil,nil, ), compileMatcher())}// NextMatcherUntilNodes is like NextUntilNodes, with the// option to filter the results based on a matcher. It returns a new// Selection object containing the matched elements.func ( *Selection) ( Matcher, ...*html.Node) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingNextUntil,nil, ), )}// PrevFilteredUntil is like PrevUntil, with the option to filter// the results based on a selector string.// It returns a new Selection object containing the matched elements.func ( *Selection) (, string) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingPrevUntil,compileMatcher(), nil), compileMatcher())}// PrevFilteredUntilMatcher is like PrevUntilMatcher, with the option to filter// the results based on a matcher.// It returns a new Selection object containing the matched elements.func ( *Selection) (, Matcher) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingPrevUntil, , nil), )}// PrevFilteredUntilSelection is like PrevUntilSelection, with the// option to filter the results based on a selector string. It returns a new// Selection object containing the matched elements.func ( *Selection) ( string, *Selection) *Selection {return .PrevMatcherUntilSelection(compileMatcher(), )}// PrevMatcherUntilSelection is like PrevUntilSelection, with the// option to filter the results based on a matcher. It returns a new// Selection object containing the matched elements.func ( *Selection) ( Matcher, *Selection) *Selection {if == nil {return .PrevMatcher() }return .PrevMatcherUntilNodes(, .Nodes...)}// PrevFilteredUntilNodes is like PrevUntilNodes, with the// option to filter the results based on a selector string. It returns a new// Selection object containing the matched elements.func ( *Selection) ( string, ...*html.Node) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingPrevUntil,nil, ), compileMatcher())}// PrevMatcherUntilNodes is like PrevUntilNodes, with the// option to filter the results based on a matcher. It returns a new// Selection object containing the matched elements.func ( *Selection) ( Matcher, ...*html.Node) *Selection {returnfilterAndPush(, getSiblingNodes(.Nodes, siblingPrevUntil,nil, ), )}// Filter and push filters the nodes based on a matcher, and pushes the results// on the stack, with the srcSel as previous selection.func filterAndPush( *Selection, []*html.Node, Matcher) *Selection {// Create a temporary Selection with the specified nodes to filter using winnow := &Selection{, .document, nil}// Filter based on matcher and push on stackreturnpushStack(, winnow(, , true))}// Internal implementation of Find that return raw nodes.func findWithMatcher( []*html.Node, Matcher) []*html.Node {// Map nodes to find the matches within the children of each nodereturnmapNodes(, func( int, *html.Node) ( []*html.Node) {// Go down one level, becausejQuery's Find selects only within descendantsfor := .FirstChild; != nil; = .NextSibling {if .Type == html.ElementNode { = append(, .MatchAll()...) } }return })}// Internal implementation to get all parent nodes, stopping at the specified// node (or nil if no stop).func getParentsNodes( []*html.Node, Matcher, []*html.Node) []*html.Node {returnmapNodes(, func( int, *html.Node) ( []*html.Node) {for := .Parent; != nil; = .Parent { := newSingleSelection(, nil)if != nil {if .IsMatcher() {break } } elseiflen() > 0 {if .IsNodes(...) {break } }if .Type == html.ElementNode { = append(, ) } }return })}// Internal implementation of sibling nodes that return a raw slice of matches.func getSiblingNodes( []*html.Node, siblingType, Matcher, []*html.Node) []*html.Node {varfunc(*html.Node) bool// If the requested siblings are ...Until, create the test function to // determine if the until condition is reached (returns true if it is)if == siblingNextUntil || == siblingPrevUntil { = func( *html.Node) bool {if != nil {// Matcher-based condition := newSingleSelection(, nil)return .IsMatcher() } elseiflen() > 0 {// Nodes-based condition := newSingleSelection(, nil)return .IsNodes(...) }returnfalse } }returnmapNodes(, func( int, *html.Node) []*html.Node {returngetChildrenWithSiblingType(.Parent, , , ) })}// Gets the children nodes of each node in the specified slice of nodes,// based on the sibling type request.func getChildrenNodes( []*html.Node, siblingType) []*html.Node {returnmapNodes(, func( int, *html.Node) []*html.Node {returngetChildrenWithSiblingType(, , nil, nil) })}// Gets the children of the specified parent, based on the requested sibling// type, skipping a specified node if required.func getChildrenWithSiblingType( *html.Node, siblingType, *html.Node,func(*html.Node) bool) ( []*html.Node) {// Create the iterator functionvar = func( *html.Node) ( *html.Node) {// Based on the sibling type requested, iterate the right wayfor {switch {casesiblingAll, siblingAllIncludingNonElements:if == nil {// First iteration, start with first child of parent // Skip node if requiredif = .FirstChild; == && != nil { = .NextSibling } } else {// Skip node if requiredif = .NextSibling; == && != nil { = .NextSibling } }casesiblingPrev, siblingPrevAll, siblingPrevUntil:if == nil {// Start with previous sibling of the skip node = .PrevSibling } else { = .PrevSibling }casesiblingNext, siblingNextAll, siblingNextUntil:if == nil {// Start with next sibling of the skip node = .NextSibling } else { = .NextSibling }default:panic("Invalid sibling type.") }if == nil || .Type == html.ElementNode || == siblingAllIncludingNonElements {return }// Not a valid node, try again from this one = } }for := (nil); != nil; = () {// If this is an ...Until case, test before append (returns true // if the until condition is reached)if == siblingNextUntil || == siblingPrevUntil {if () {return } } = append(, )if == siblingNext || == siblingPrev {// Only one node was requested (immediate next or previous), so exitreturn } }return}// Internal implementation of parent nodes that return a raw slice of Nodes.func getParentNodes( []*html.Node) []*html.Node {returnmapNodes(, func( int, *html.Node) []*html.Node {if .Parent != nil && .Parent.Type == html.ElementNode {return []*html.Node{.Parent} }returnnil })}// Internal map function used by many traversing methods. Takes the source nodes// to iterate on and the mapping function that returns an array of nodes.// Returns an array of nodes mapped by calling the callback function once for// each node in the source nodes.func mapNodes( []*html.Node, func(int, *html.Node) []*html.Node) ( []*html.Node) { := make(map[*html.Node]bool)for , := range {if := (, ); len() > 0 { = appendWithoutDuplicates(, , ) } }return}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.